
package com.rexolar.openapi.context;

import com.rexolar.openapi.utlis.HttpUtil;
import com.rexolar.openapi.utlis.IpAddressUtil;
import lombok.NoArgsConstructor;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * OpenContextUtil
 *
 * @author lvqi09211
 **/
@NoArgsConstructor
public class OpenContextUtil {

    /**
     * Store the context in ThreadLocal for easy access.
     */
    private static ThreadLocal<OpenContext> contextHolder = new ThreadLocal<>();

    private static final ReentrantLock LOCK = new ReentrantLock();


    /**
     *
     * @param httpServletRequest
     * @return
     */
    public static OpenContext enter(HttpServletRequest httpServletRequest) {

                    OpenContext context = contextHolder.get();
                    if (context == null) {
                        LOCK.lock();
                        try {

                            String requestIp = IpAddressUtil.getIpAddr(httpServletRequest);
                            Map<String, String> paramsMap = HttpUtil.paramsToMap(httpServletRequest);
                context = new OpenContext(requestIp, paramsMap, httpServletRequest.getRequestURI());
                contextHolder.set(context);

            } finally {
                LOCK.unlock();
            }
        }
        return context;
    }

    /**
     *
     */
    public static void exit() {
        OpenContext context = contextHolder.get();
        if (context != null) {
            contextHolder.set(null);
        }
    }


    /**
     *
     * @return
     */
    public static OpenContext getContext() {
        return contextHolder.get();
    }

    /**
     * @param newContext new context to set
     * @return old context
     */
    public static OpenContext setContext(OpenContext newContext) {
        OpenContext context = contextHolder.get();
        if (context == null) {
            LOCK.lock();
            try {
                contextHolder.set(newContext);
            } finally {
                LOCK.unlock();
            }
        }
        return context;
    }
    /**
     * @param newContext new context to set
     * @return old context
     */
    static OpenContext replaceContext(OpenContext newContext) {
        OpenContext backupContext = contextHolder.get();
        if (newContext == null) {
            contextHolder.remove();
        } else {
            contextHolder.set(newContext);
        }
        return backupContext;
    }
}
